package com.opennews.openplatform

import groovy.transform.CompileStatic

import java.text.SimpleDateFormat

@CompileStatic
class DateHelper {
    final static String LONG_DATE = "yyyy-MM-dd"
    final static String LONG_DATE_TIME = "yyyy-MM-dd HH:mm:ss"
    final static String LONG_TIMESTAMP = "yyyyMMddHHmmSSS"
    final static String UTC_LONG_DATE_TIME = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"

    /**
     * Gets current system date.
     * @return The Date instance of current date.
     */
    static Date getCurrentDate() {
        return new Date()
    }

    /**
     * Parses the input string to date with specific format.
     * @param dateStr: The string contains date value.
     * @param dateFormat: The date format.
     * @return The date instance.
     */
    static Date parseToDate(String dateStr, String dateFormat) {
        return SharedUtil.isNullOrEmpty(dateStr) || SharedUtil.isNullOrEmpty(dateFormat) ? null : new SimpleDateFormat(dateFormat).parse(dateStr)
    }

    /**
     * Parses the input string to date with specific format.
     * @param dateStr: The string contains date value.
     * @return The date instance.
     */
    static Date parseFromLongDateTime(String dateStr) {
        def dateFormat = dateStr.contains("T") || dateStr.endsWith("Z") ? UTC_LONG_DATE_TIME : LONG_DATE_TIME

        return parseToDate(dateStr, dateFormat)
    }

    /**
     * Gets the first day of the month based on the provided date.
     * Example: If date is 2019-12-13, the return value is 2019-12-1.
     * @param date: The any day in a month.
     * @return The first day of the month.
     */
    static Date getFirstDayOfMonth(Date date) {
        def calendar = Calendar.getInstance()
        calendar.setTime(date)
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH))

        return calendar.getTime()
    }

    /**
     * Gets the first day of the month based on the provided year and month.
     * @param year: The int of year.
     * @param month: The int of month.
     * @return The first day of the month in the year.
     */
    static Date getFirstDayOfMonth(int year, int month) {
        // Please be aware, month value is 0-based. e.g., 0 for January.
        def calendar = new GregorianCalendar(year, month - 1, 1)

        return calendar.getTime()
    }

    /**
     * Gets the first day of the next month based on the provided year and month.
     * @param year: The int of year.
     * @param month: The int of month.
     * @return The first day of the next month in the year.
     */
    static Date getLastDayOfMonth(int year, int month) {
        // Please be aware, month value is 0-based. e.g., 0 for January.
        def firstDay = getFirstDayOfNextMonth(year, month)
        def calendar = Calendar.getInstance()
        calendar.setTime(firstDay)
        calendar.add(Calendar.DATE, -1)

        return calendar.getTime()
    }

    /**
     * Gets the first day of the next month based on the provided year and month.
     * @param year: The int of year.
     * @param month: The int of month.
     * @return The first day of the next month in the year.
     */
    static Date getFirstDayOfNextMonth(int year, int month) {
        // Please be aware, month value is 0-based. e.g., 0 for January.
        def calendar = new GregorianCalendar(year, month - 1, 1)
        calendar.add(Calendar.MONTH, 1)

        return calendar.getTime()
    }
}